﻿//-----------------------------------------------------------------------
// <copyright file="ImageSearchSlideShow.cs" company="Microsoft">
//     (c) 2009 Microsoft corp.
//     This software is distributed under Microsoft Public License (MSPL)
//     see http://opensource.org/licenses/ms-pl.html
// </copyright>
//-----------------------------------------------------------------------
[assembly:System.Web.UI.TagPrefix("LiveSearchApiPowerToys.Controls", "lsPToys")]
namespace LiveSearchApiPowerToys.Controls
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.ComponentModel.Design.Serialization;
    using System.Drawing.Design;
    using System.Globalization;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.Design;
    using System.Web.UI.WebControls;

    using AjaxControlToolkit;
    using LiveSearchApiPowerToys.Components;

    /// <summary>
    /// ImageSearchSlideShow is a composite control showing an endless slideshow of images fulfilling a given
    /// query string and parameters.
    /// </summary>
    [DefaultProperty("Query")]
    [ToolboxData("<{0}:ImageSearchSlideshow runat=server></{0}:ImageSearchSlideshow>")]
    [PersistChildren(false)]
    [ParseChildren(true, "Query")]
    public class ImageSearchSlideshow : CompositeControl
    {
        /// <summary>
        /// the maximyum number of the images requested to Live Search
        /// </summary>
        private int maxNumOfImages;

        /// <summary>
        /// the panel containing the buttons that control the slideshow 
        /// </summary>
        private Panel myBtnPanel;

        /// <summary>
        /// the panel containing the control
        /// </summary>
        private Panel myCtrlPanel;

        /// <summary>
        /// the description of the current image
        /// </summary>
        private Label myDescriptionLabel;
        
        /// <summary>
        /// the panel containing the description
        /// </summary>
        private Panel myDescriptionPanel;

        /// <summary>
        /// the current image loaded into the control
        /// </summary>
        private Image myImage;

        /// <summary>
        /// the button advancing to next image
        /// </summary>
        private Button myNextBtn;

        /// <summary>
        /// the button starting or pausing the slideshow
        /// </summary>
        private Button myPlayBtn;

        /// <summary>
        /// the button reverting to the previous image
        /// </summary>
        private Button myPrevBtn;

        /// <summary>
        /// the Live Search logo
        /// </summary>
        private Image myLiveLogo;

        /// <summary>
        /// the attribution text to Live Search
        /// </summary>
        private Label myLiveString;

        /// <summary>
        /// the AJAX Control Toolkit SlideShowExtender object used to implement the slideshow behavior
        /// </summary>
        private AjaxControlToolkit.SlideShowExtender mySSExt;

        /// <summary>
        /// the title of the image
        /// </summary>
        private Label myTitleLabel;

        /// <summary>
        /// the panel containing the title
        /// </summary>
        private Panel myTitlePanel;

        /// <summary>
        /// the text for the next button
        /// </summary>
        private string nextButtonText;

        /// <summary>
        /// the text for the play button
        /// </summary>
        private string playButtonText;

        /// <summary>
        /// the text for the prev button
        /// </summary>
        private string prevButtonText;

        /// <summary>
        /// the text for the stop button
        /// </summary>
        private string stopButtonText;

        /// <summary>
        /// Gets or sets the CSS class applied to the buttons in the control
        /// </summary>
        [Category("Appearance")]
        [Browsable(true)]
        [Description("CSS Class name applied to control's buttons.")]
        [CssClassProperty]
        public String ButtonsCssClass { get; set; }

        /// <summary>
        /// Gets or sets the time interval for the caching of this image query.
        /// </summary>
        [Category("Caching")]
        [Localizable(false)]
        [PersistenceMode(PersistenceMode.Attribute), MergableProperty(false), TypeConverter(typeof(TimeSpanConverter))]
        [Description("Cache expiration interval for this query")]
        public TimeSpan CacheExpirationInterval { get; set; }
        
        /// <summary>
        /// Gets or sets the identifier for the caching of this image query
        /// </summary>
        private Guid _CacheIdentifier;
        [Category("Caching")]
        [PersistenceMode(PersistenceMode.Attribute), MergableProperty(false), TypeConverter(typeof(GuidConverter))]
        [Localizable(false)]
        [Description("Query Cache Identifier.")]
        public Guid CacheIdentifier { get; set; }

        /// <summary>
        /// Gets or sets  the CSS class applied to the image description label
        /// </summary>
        [Category("Appearance")]
        [Browsable(true)]
        [Description("CSS Class name applied to Image Description label.")]
        [CssClassProperty]
        public string DescriptionCssClass { get; set; }
        
        /// <summary>
        /// Gets or sets the CSS Class name applied to the Panel containing the Image Description label
        /// </summary>
        [Category("Appearance")]
        [Browsable(true)]
        [Description("CSS Class name applied to the Panel containing the Image Description label.")]
        [CssClassProperty]
        public string DescriptionPanelCssClass { get; set; }

        /// <summary>
        /// Gets or sets  the URL of the first image assigned to the control
        /// </summary>
        [Category("Appearance")]
        [Localizable(false)]
        [Description("URL of the first image assigned to the control.")]
        [UrlProperty("*.jpg;*.gif;*.bmp;*.png")]
        [Editor(typeof(UrlEditor), typeof(UITypeEditor))]
        public string FirstImage { get; set; }
        
        /// <summary>
        /// Gets or sets  the Image Aspect Ratio: Wide, Tall, Square
        /// </summary>
        [Category("Search")]
        [Localizable(false)]
        [Description("Image Aspect Ratio: Wide, Tall, Square.")]
        public ImageAspectRatioOption? ImageAspectRatio { get; set; }
        
        /// <summary>
        /// Gets or sets the Image Color: Color or Black &amp; White
        /// </summary>
        [Category("Search")]
        [Localizable(false)]
        [Description("Image Colore: Color or Black & White.")]
        public ImageColorsOption? ImageColor { get; set; }

        /// <summary>
        /// Gets or sets  the Image Size: Small, Medium or Large
        /// </summary>
        [Category("Search")]
        [Localizable(false)]
        [Description("Image Size: Small, Medium or Large.")]
        public ImageSizesOption? ImageSize { get; set; }        

        /// <summary>
        /// Gets or sets  the Image Subjects: NonPortrait, Portrait, FacePortrait
        /// </summary>        
        [Category("Search")]
        [Localizable(false)]
        [Description("Image Subjects: NonPortrait, Portrait, FacePortrait.")]
        public ImageSubjectOption? ImageSubject { get; set; }
        
        /// <summary>
        /// Gets or sets  the Image Type: Photo or Graphics
        /// </summary>
        [Category("Search")]
        [Localizable(false)]
        [Description("Image Type: Photo or Graphics.")]
        public ImageTypeOption? ImageType { get; set; }

        /// <summary>
        /// Gets or sets  the maximum number of images requested
        /// </summary>
        [Category("Search")]
        [Localizable(false)]
        [Description("Maximum number of images requested.")]
        public int MaxNumberOfImages
        {
            get { return (maxNumOfImages == 0) ? 100 : maxNumOfImages; }
            set { maxNumOfImages = value; }
        }

        /// <summary>
        /// Gets or sets  the display text for the button advancing to next image in the show
        /// </summary>
        [Category("Appearance")]
        [Localizable(false)]
        [Description("Next button display text.")]
        public string NextButtonText
        {
            get
            {
                return (String.IsNullOrEmpty(nextButtonText) ? "Next" : nextButtonText);
            }

            set
            {
                nextButtonText = value;
            }
        }

        /// <summary>
        /// Gets or sets  the display text for the button starting or pausing the show
        /// </summary>
        
        [Category("Appearance")]
        [Localizable(false)]
        [Description("Play button display text.")]
        public string PlayButtonText
        {
            get
            {
                return (String.IsNullOrEmpty(playButtonText) ? "Play" : playButtonText);
            }

            set
            {
                playButtonText = value;
            }
        }

        /// <summary>
        /// Gets or sets  the display text for the button reverting to previous image in the show
        /// </summary>
        
        [Category("Appearance")]
        [Localizable(false)]
        [Description("Previous button display text.")]
        public string PreviousButtonText
        {
            get
            {
                return (String.IsNullOrEmpty(prevButtonText) ? "Prev" : prevButtonText);
            }

            set
            {
                prevButtonText = value;
            }
        }

        /// <summary>
        /// Gets or sets  the query text expression actually sent to the Live Search service
        /// </summary>
        
        [Category("Search")]
        [DefaultValue("")]
        [Localizable(false)]
        [Description("Query text expression as accepted by Live Search.")]
        public string Query { get; set; }

        /// <summary>
        /// Gets or sets  the display text for the button stopping the show
        /// </summary>        
        [Category("Appearance")]
        [Localizable(false)]
        [Description("Stop button display text.")]
        public string StopButtonText
        {
            get
            {
                return (String.IsNullOrEmpty(stopButtonText) ? "Stop" : stopButtonText);
            }

            set
            {
                stopButtonText = value;
            }
        }

        /// <summary>
        /// Gets or sets  the CSS Class name applied to the image title
        /// </summary>
        [Category("Appearance")]
        [Description("CSS Class name applied to Image Title label.")]
        [CssClassProperty]
        public string TitleCssClass { get; set; }
       
        /// <summary>
        /// Gets or sets  the CSS Class name applied to the Panel containing the Image Title label
        /// </summary>
        [Category("Appearance")]
        [Description("CSS Class name applied to the Panel containing the Image Title label.")]
        [CssClassProperty]
        public string TitlePanelCssClass { get; set; }
        
        /// <summary>
        /// Called when the control is initialized - it creates the child controls
        /// </summary>
        protected override void CreateChildControls()
        {
            // Clear child controls
            Controls.Clear();

            // Build control tree
            this.CreateControls();

            ClearChildViewState();

            base.CreateChildControls();
        }

        /// <summary>
        /// Creates the child controls when the control is initialized
        /// </summary>
        protected virtual void CreateControls()
        {
            // Create controls used to compose this control
            this.myCtrlPanel = new Panel();
            this.myTitlePanel = new Panel();
            this.myTitleLabel = new Label();
            this.myImage = new Image();
            this.myDescriptionPanel = new Panel();
            this.myDescriptionLabel = new Label();
            this.myBtnPanel = new Panel();
            this.myPrevBtn = new Button();
            this.myPlayBtn = new Button();
            this.myNextBtn = new Button();
            this.myLiveLogo = new Image();
            this.myLiveString = new Label();

            /*
             BUG BUG BUG - make these two resources in the configuration file
             */
            this.myLiveLogo.ImageUrl = "http://search.live.com/s/siteowner/wlbrand.jpg";
            this.myLiveString.Text = "Results by ";

            // Define Controls IDs and compose
            this.myCtrlPanel.ID = "SISS_Control";
            this.myTitlePanel.ID = "SISS_Title_Pnl";
            this.myTitleLabel.ID = "SISS_Title";
                        
            this.myTitlePanel.Controls.Add(this.myTitleLabel);
            this.myCtrlPanel.Controls.Add(this.myTitlePanel);

            this.myImage.ID = "SISS_Photo";
            if (!String.IsNullOrEmpty(this.FirstImage))
            {
                myImage.ImageUrl = this.FirstImage;
            }

            this.myCtrlPanel.Controls.Add(this.myImage);

            this.myDescriptionPanel.ID = "SISS_Description_Pnl";
            this.myDescriptionLabel.ID = "SISS_Description";

            this.myDescriptionPanel.Controls.Add(this.myDescriptionLabel);

            this.myCtrlPanel.Controls.Add(this.myDescriptionPanel);

            this.myBtnPanel.ID = "SISS_buttons";

            this.myPrevBtn.ID = "SISS_PrevBtn";
            this.myPrevBtn.Text = this.PreviousButtonText;
            this.myBtnPanel.Controls.Add(this.myPrevBtn);

            this.myPlayBtn.ID = "SISS_PlayBtn";
            this.myPlayBtn.Text = this.PlayButtonText;
            this.myBtnPanel.Controls.Add(this.myPlayBtn);

            this.myNextBtn.ID = "SISS_NextBtn";
            this.myNextBtn.Text = this.NextButtonText;
            this.myBtnPanel.Controls.Add(this.myNextBtn);

            this.myCtrlPanel.Controls.Add(this.myBtnPanel);

            if (this.mySSExt != null)
            {
                this.mySSExt.TargetControlID = this.myImage.UniqueID;
                this.mySSExt.ImageTitleLabelID = this.myTitleLabel.UniqueID;
                this.mySSExt.PreviousButtonID = this.myPrevBtn.UniqueID;
                this.mySSExt.PlayButtonID = this.myPlayBtn.UniqueID;
                this.mySSExt.NextButtonID = this.myNextBtn.UniqueID;

                this.mySSExt.ImageDescriptionLabelID = this.myDescriptionLabel.UniqueID;

                this.mySSExt.PlayButtonText = this.PlayButtonText;
                this.mySSExt.StopButtonText = this.StopButtonText;

                this.myCtrlPanel.Controls.Add((Control)this.mySSExt);
            }

            Controls.Add(this.myCtrlPanel);

            this.myCtrlPanel.Controls.Add(this.myLiveString);
            this.myCtrlPanel.Controls.Add(this.myLiveLogo);
        }

        /// <summary>
        /// Initializes the control - called by the ASP.net framework
        /// </summary>
        /// <param name="e">the event arguments - unused</param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            this.mySSExt = new AjaxControlToolkit.SlideShowExtender();
            this.mySSExt.AutoPlay = true;
            this.mySSExt.Loop = true;
            this.mySSExt.SlideShowServicePath = "~/services/imageshelper.asmx";
            this.mySSExt.SlideShowServiceMethod = "SearchPhotoEx";
            this.mySSExt.UseContextKey = true;
            this.mySSExt.ID = "SISS_SlideExt";

            if (!string.IsNullOrEmpty(this.Query))
            {
                ImageQuery myIQ = new ImageQuery(
                    this.Query, 
                    string.Empty,
                    this.ImageSize,
                    this.ImageAspectRatio,
                    this.ImageColor,
                    this.ImageType,
                    this.ImageSubject,
                    this.MaxNumberOfImages);
                this.mySSExt.ContextKey = myIQ.ToJsonRequest();
            }
        }

        /// <summary>
        /// Draws the control and its children (called by the ASP.net framework)
        /// </summary>
        /// <param name="writer">an HtmlTextWriter</param>
        protected override void Render(HtmlTextWriter writer)
        {
            // Ensure it renders at design time
            EnsureChildControls();

            // Style controls
            this.StyleControls();

            // Render Control
            RenderContents(writer);
        }

        /// <summary>
        /// Applies the appropriate styles to the control components.
        /// </summary>
        protected virtual void StyleControls()
        {
            this.myCtrlPanel.CopyBaseAttributes(this);
            this.myCtrlPanel.HorizontalAlign = HorizontalAlign.Center;
            this.myCtrlPanel.Width = this.Width.IsEmpty ? Unit.Pixel(320) : this.Width;
            this.myCtrlPanel.Height = this.Height.IsEmpty ? Unit.Pixel(240) : this.Height;

            this.myTitlePanel.CssClass = this.TitlePanelCssClass; 
            this.myTitlePanel.Width = this.myCtrlPanel.Width;
            this.myTitlePanel.Height = Unit.Pixel(40);

            this.myTitleLabel.CssClass = this.TitleCssClass; 
            this.myTitleLabel.ControlStyle.Font.Bold = true;
            this.myTitleLabel.ControlStyle.Font.Italic = true;
            this.myTitleLabel.ControlStyle.Font.Size = FontUnit.Point(12);

            this.myImage.Width = new Unit(this.myCtrlPanel.Width.Value - 10, UnitType.Pixel);
            this.myImage.Height = Unit.Pixel((int)this.myCtrlPanel.Height.Value - 30 - 65);
            this.myImage.ImageAlign = ImageAlign.Bottom;

            this.myDescriptionPanel.CssClass = this.DescriptionPanelCssClass; 
            this.myDescriptionPanel.Width = this.myCtrlPanel.Width;
            this.myDescriptionPanel.Height = Unit.Pixel(25);

            this.myDescriptionLabel.CssClass = this.DescriptionCssClass; 
            this.myDescriptionLabel.ControlStyle.Font.Bold = true;
            this.myDescriptionLabel.ControlStyle.Font.Italic = true;
            this.myDescriptionLabel.ControlStyle.Font.Size = FontUnit.Point(10);

            this.myBtnPanel.Height = Unit.Pixel(30);
            this.myBtnPanel.Width = this.myImage.Width;

            this.myPrevBtn.CssClass = this.ButtonsCssClass; 
            this.myPrevBtn.Height = Unit.Pixel(24);
            this.myPrevBtn.Width = Unit.Percentage(20);
            this.myPrevBtn.Font.Size = FontUnit.Point(9);

            this.myPlayBtn.CssClass = this.ButtonsCssClass;
            this.myPlayBtn.Height = Unit.Pixel(24);
            this.myPlayBtn.Width = Unit.Percentage(20);
            this.myPrevBtn.Font.Size = FontUnit.Point(9);

            this.myNextBtn.CssClass = this.ButtonsCssClass;
            this.myNextBtn.Height = Unit.Pixel(24);
            this.myNextBtn.Width = Unit.Percentage(20);
            this.myNextBtn.Font.Size = FontUnit.Point(9);

            this.myLiveString.ControlStyle.Font.Size = FontUnit.Point(10); 
            this.myLiveLogo.ImageAlign = ImageAlign.Middle;
        }
    }
}
